package com.ruoyi.web.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.web.domain.MonitorArea;
import com.ruoyi.web.domain.TreeSelect;
import com.ruoyi.web.domain.dto.MonitorAreaDto;
import com.ruoyi.web.domain.vo.MonitorAreaTreeVo;
import com.ruoyi.web.domain.vo.MonitorAreaVo;
import com.ruoyi.web.mapper.MonitorAreaMapper;
import com.ruoyi.web.mapper.MonitorCameraMapper;
import com.ruoyi.web.service.IMonitorAreaService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class MonitorAreaServiceImpl extends ServiceImpl<MonitorAreaMapper, MonitorArea> implements IMonitorAreaService {

    @Autowired
    private MonitorAreaMapper monitorAreaMapper;

    @Autowired
    private MonitorCameraMapper monitorCameraMapper;

    @Override
    public AjaxResult add(MonitorAreaDto dto) {
        // 校验当前区域下是否已存在该名称的子区域
        MonitorArea repetitiveArea = monitorAreaMapper.selectOne(new LambdaQueryWrapper<MonitorArea>().eq(MonitorArea::getBaseParentId, dto.getBaseParentId()).eq(MonitorArea::getBaseName, dto.getBaseName()).eq(MonitorArea::getIsDelete, 0));
        if (repetitiveArea != null) {
            return AjaxResult.error("当前区域下已存在该名称的子区域");
        }
        MonitorArea monitorArea = new MonitorArea();
        BeanUtils.copyProperties(dto, monitorArea);
        List<MonitorArea> monitorAreas = monitorAreaMapper.selectList(new LambdaQueryWrapper<MonitorArea>().eq(MonitorArea::getBaseParentId, dto.getBaseParentId()).eq(MonitorArea::getIsDelete, 0).orderByDesc(MonitorArea::getSort));
        if (monitorAreas.isEmpty()) {
            monitorArea.setSort(0);
            MonitorArea parentMonitorArea = monitorAreaMapper.selectById(dto.getBaseParentId());
            monitorArea.setAncestors(parentMonitorArea.getAncestors() + "," + parentMonitorArea.getBaseId());
        } else {
            monitorArea.setSort(monitorAreas.get(0).getSort() + 1);
            monitorArea.setAncestors(monitorAreas.get(0).getAncestors());
        }
        monitorArea.setCreator(SecurityUtils.getUserId());
        monitorArea.setCreateTime(LocalDateTime.now());
        monitorArea.setUpdateTime(LocalDateTime.now());
        monitorAreaMapper.insert(monitorArea);
        return AjaxResult.success("新增成功");
    }

    @Override
    public List<MonitorAreaTreeVo> getTreeVoList(MonitorAreaDto dto) {
        return monitorAreaMapper.selectTreeVoList(dto);
    }

    @Override
    public List<MonitorAreaTreeVo> getCameraTreeVoList(MonitorAreaDto dto) {
        return monitorAreaMapper.selectCameraTreeVoList(dto);
    }

    @Override
    public List<TreeSelect> buildMonitorAreaTreeSelect(List<MonitorAreaTreeVo> list) {
        List<MonitorAreaTreeVo> deptTrees = this.buildDeptTree(list);
        return deptTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
    }

    public List<MonitorAreaTreeVo> buildDeptTree(List<MonitorAreaTreeVo> list) {
        List<MonitorAreaTreeVo> returnList = new ArrayList<>();
        List<Long> tempList = list.stream().map(MonitorAreaTreeVo::getBaseId).collect(Collectors.toList());
        Iterator<MonitorAreaTreeVo> iterator = list.iterator();
        MonitorAreaTreeVo monitorArea;
        while (iterator.hasNext()) {
            monitorArea = iterator.next();
            if (!tempList.contains(monitorArea.getBaseParentId())) {
                this.recursionFn(list, monitorArea);
                returnList.add(monitorArea);
            }
        }
        if (returnList.isEmpty()) {
            returnList = list;
        }
        return returnList;
    }

    private void recursionFn(List<MonitorAreaTreeVo> list, MonitorAreaTreeVo t) {
        List<MonitorAreaTreeVo> childList = this.getChildList(list, t);
        t.setChildren(childList);
        Iterator<MonitorAreaTreeVo> iterator = childList.iterator();
        while (true) {
            MonitorAreaTreeVo tChild;
            do {
                if (!iterator.hasNext()) {
                    return;
                }
                tChild = iterator.next();
            } while (!this.hasChild(list, tChild));
            Iterator<MonitorAreaTreeVo> it = childList.iterator();
            while (it.hasNext()) {
                MonitorAreaTreeVo n = it.next();
                this.recursionFn(list, n);
            }
        }
    }

    private List<MonitorAreaTreeVo> getChildList(List<MonitorAreaTreeVo> list, MonitorAreaTreeVo t) {
        List<MonitorAreaTreeVo> childList = new ArrayList<>();
        Iterator<MonitorAreaTreeVo> iterator = list.iterator();
        while (iterator.hasNext()) {
            MonitorAreaTreeVo n = iterator.next();
            if (n.getBaseParentId() != null && n.getBaseParentId().equals(t.getBaseId())) {
                childList.add(n);
            }
        }
        return childList;
    }

    private boolean hasChild(List<MonitorAreaTreeVo> list, MonitorAreaTreeVo t) {
        return !this.getChildList(list, t).isEmpty();
    }

    @Override
    public AjaxResult rename(MonitorAreaDto dto) {
        Long baseId = dto.getBaseId();
        String baseName = dto.getBaseName();
        MonitorArea monitorArea = monitorAreaMapper.selectById(baseId);
        MonitorArea repetitiveArea = monitorAreaMapper.selectOne(new LambdaQueryWrapper<MonitorArea>().eq(MonitorArea::getBaseParentId, monitorArea.getBaseParentId()).eq(MonitorArea::getBaseName, baseName).eq(MonitorArea::getIsDelete, 0));
        if (repetitiveArea != null) {
            return AjaxResult.error("当前区域下已存在该名称的子区域");
        }
        monitorAreaMapper.update(new LambdaUpdateWrapper<MonitorArea>().eq(MonitorArea::getBaseId, baseId).set(MonitorArea::getBaseName, baseName).set(MonitorArea::getModifier, SecurityUtils.getUserId()).set(MonitorArea::getUpdateTime, LocalDateTime.now()));
        return AjaxResult.success("操作成功");
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public AjaxResult move(MonitorAreaDto dto) {
        MonitorArea monitorArea = monitorAreaMapper.selectById(dto.getBaseId());
        ArrayList<MonitorArea> updatedMonitorAreas = new ArrayList<>();
        String direction = dto.getDirection();
        if (StringUtils.equals(direction, "1")) {
            // 上移
            if (monitorArea.getSort() == 0) {
                return AjaxResult.error("当前区域已经是第一个");
            }
            MonitorArea lastMonitorArea = monitorAreaMapper.selectOne(new LambdaQueryWrapper<MonitorArea>().eq(MonitorArea::getBaseParentId, monitorArea.getBaseParentId()).eq(MonitorArea::getSort, monitorArea.getSort() - 1).eq(MonitorArea::getIsDelete, 0));
            lastMonitorArea.setSort(monitorArea.getSort());
            updatedMonitorAreas.add(lastMonitorArea);
            monitorArea.setSort(monitorArea.getSort() - 1);
            updatedMonitorAreas.add(monitorArea);
        } else if (StringUtils.equals(direction, "2")) {
            // 下移
            List<MonitorArea> monitorAreas = monitorAreaMapper.selectList(new LambdaQueryWrapper<MonitorArea>().eq(MonitorArea::getBaseParentId, monitorArea.getBaseParentId()).eq(MonitorArea::getIsDelete, 0).orderByDesc(MonitorArea::getSort));
            if (Objects.equals(monitorAreas.get(0).getSort(), monitorArea.getSort())) {
                return AjaxResult.error("当前区域已经是最后一个");
            }
            MonitorArea nextMonitorArea = monitorAreaMapper.selectOne(new LambdaQueryWrapper<MonitorArea>().eq(MonitorArea::getBaseParentId, monitorArea.getBaseParentId()).eq(MonitorArea::getSort, monitorArea.getSort() + 1).eq(MonitorArea::getIsDelete, 0));
            nextMonitorArea.setSort(monitorArea.getSort());
            updatedMonitorAreas.add(nextMonitorArea);
            monitorArea.setSort(monitorArea.getSort() + 1);
            updatedMonitorAreas.add(monitorArea);
        } else {
            return AjaxResult.error("请正确传参");
        }
        if (updatedMonitorAreas.size() > 0) {
            this.updateBatchById(updatedMonitorAreas);
        }
        return AjaxResult.success("操作成功");
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public AjaxResult delete(MonitorAreaDto dto) {
        // 查询当前区域下是否存在摄像头，若存在则不允许删除
        List<MonitorArea> monitorCameras = monitorAreaMapper.selectList(new LambdaQueryWrapper<MonitorArea>().eq(MonitorArea::getBaseParentId, dto.getBaseId()).eq(MonitorArea::getIsDelete, 0).eq(MonitorArea::getType, "2"));
        if (!monitorCameras.isEmpty()) {
            return AjaxResult.error("当前区域下存在摄像头，请先删除摄像头");
        }
        // 查询当前区域下是否存在子区域，若存在则不允许删除
        List<MonitorArea> monitorSubAreas = monitorAreaMapper.selectList(new LambdaQueryWrapper<MonitorArea>().eq(MonitorArea::getBaseParentId, dto.getBaseId()).eq(MonitorArea::getIsDelete, 0).eq(MonitorArea::getType, "1"));
        if (!monitorSubAreas.isEmpty()) {
            return AjaxResult.error("当前区域下存在子区域，请先删除子区域");
        }
        MonitorArea monitorArea = monitorAreaMapper.selectById(dto.getBaseId());
        monitorArea.setModifier(SecurityUtils.getUserId());
        monitorArea.setUpdateTime(LocalDateTime.now());
        monitorArea.setIsDelete(Byte.valueOf("1"));
        monitorAreaMapper.updateById(monitorArea);
        // 调整删除后数据的顺序
        List<MonitorArea> monitorAreas = monitorAreaMapper.selectList(new LambdaQueryWrapper<MonitorArea>().eq(MonitorArea::getBaseParentId, monitorArea.getBaseParentId()).eq(MonitorArea::getIsDelete, 0).gt(MonitorArea::getSort, monitorArea.getSort()));
        List<MonitorArea> updatedMonitorAreas = monitorAreas.stream().peek(item -> item.setSort(item.getSort() - 1)).collect(Collectors.toList());
        this.updateBatchById(updatedMonitorAreas);
        return AjaxResult.success("删除成功");
    }

    @Override
    public MonitorAreaVo getDetails(Long baseId) {
        return monitorAreaMapper.selectDetails(baseId);
    }

    @Override
    public List<MonitorAreaVo> getList(MonitorAreaDto dto) {
        return monitorAreaMapper.selectAreaList(dto);
    }

    @Override
    public Map<String, Integer> getAllCamerasCount() {
        return monitorAreaMapper.selectAllCamerasCount();
    }
}
